﻿using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Beaker.Common.Specs
{
	[TestClass]
	public sealed class MaybeStaticSpecs
	{
		#region Create

		[TestMethod]
		public void CreateWithoutValueShouldCreateAMaybeOfProvidedTypeAndNoValue()
		{
			IMaybe maybe = Maybe.Create(typeof(int));

			maybe.Should().BeOfType<Maybe<int>>();
			maybe.HasValue.Should().BeFalse();
		}

		[TestMethod]
		public void TypedCreateWithoutValueShouldCreateAMaybeOfProvidedTypeAndNoValue()
		{
			IMaybe maybe = Maybe.Create<int>();

			maybe.Should().BeOfType<Maybe<int>>();
			maybe.HasValue.Should().BeFalse();
		}

		[TestMethod]
		public void CreateWithValueShouldCreateAMaybeOfProvidedTypeAndGivenValue()
		{
			IMaybe maybe = Maybe.Create(typeof(int), -532);

			maybe.Should().BeOfType<Maybe<int>>();
			maybe.HasValue.Should().BeTrue();
			maybe.Value.Should().Be(-532);
		}

		[TestMethod]
		public void TypedCreateWithValueShouldCreateAMaybeOfProvidedTypeAndGivenValue()
		{
			IMaybe maybe = Maybe.Create<int>(-532);

			maybe.Should().BeOfType<Maybe<int>>();
			maybe.HasValue.Should().BeTrue();
			maybe.Value.Should().Be(-532);
		}

		[TestMethod]
		public void CreateWithNullReferenceAsValueShouldCreateAMaybeOfProvidedTypeAndValueMatchingANullReference()
		{
			IMaybe maybe = Maybe.Create(typeof(int?), null);

			maybe.Should().BeOfType<Maybe<int?>>();
			maybe.HasValue.Should().BeTrue();
			maybe.Value.Should().Be(null);
		}

		[TestMethod]
		public void TypedCreateWithNullReferenceAsValueShouldCreateAMaybeOfProvidedTypeAndValueMatchingANullReference()
		{
			IMaybe maybe = Maybe.Create<int?>(null);

			maybe.Should().BeOfType<Maybe<int?>>();
			maybe.HasValue.Should().BeTrue();
			maybe.Value.Should().Be(null);
		}

		[TestMethod]
		public void CreateWithNullConversionAndWithNullReferenceAsValueShouldCreateAMaybeOfProvidedTypeAndNoValue()
		{
			IMaybe maybe = Maybe.CreateWithNullConversion(typeof(int?), null);

			maybe.Should().BeOfType<Maybe<int?>>();
			maybe.HasValue.Should().BeFalse();
		}

		[TestMethod]
		public void TypedCreateWithNullConversionAndWithNullReferenceAsValueShouldCreateAMaybeOfProvidedTypeAndNoValue()
		{
			IMaybe maybe = Maybe.CreateWithNullConversion<int?>(null);

			maybe.Should().BeOfType<Maybe<int?>>();
			maybe.HasValue.Should().BeFalse();
		}

		#endregion

		[TestMethod]
		public void GetUnderlyingClass()
		{
			Maybe.GetUnderlyingType(typeof(Maybe<double>))
				.Should().Be(typeof(double));
		}
	}
}
